suppressed content but not suppress it ("suppressrevision" right).
* Added a new hook, "OutputPageScriptsForBottomQueue", to add modules to the
bottom queue that should be requested in a dedicated <script> request.
+* (bug 66440) The MediaWiki web installer will now allow you to choose the skins
+ to enable (from the ones included in download tarball) and decide which one
+ should be the default.
=== Bug fixes in 1.24 ===
* (bug 49116) Footer copyright notice is now always displayed in user language
'_LicenseCode' => 'none',
'_CCDone' => false,
'_Extensions' => array(),
+ '_Skins' => array(),
'_MemCachedServers' => '',
'_UpgradeKeySupplied' => false,
'_ExistingDBSettings' => false,
}
/**
- * Finds extensions that follow the format /extensions/Name/Name.php,
+ * Finds extensions that follow the format /$directory/Name/Name.php,
* and returns an array containing the value for 'Name' for each found extension.
*
+ * Reasonable values for $directory include 'extensions' (the default) and 'skins'.
+ *
+ * @param string $directory Directory to search in
* @return array
*/
- public function findExtensions() {
+ public function findExtensions( $directory = 'extensions' ) {
if ( $this->getVar( 'IP' ) === null ) {
return array();
}
- $extDir = $this->getVar( 'IP' ) . '/extensions';
+ $extDir = $this->getVar( 'IP' ) . '/' . $directory;
if ( !is_readable( $extDir ) || !is_dir( $extDir ) ) {
return array();
}
$this->installer = $installer;
$this->extensions = $installer->getVar( '_Extensions' );
+ $this->skins = $installer->getVar( '_Skins' );
$db = $installer->getDBInstaller( $installer->getVar( 'wgDBtype' ) );
/**
* Return the full text of the generated LocalSettings.php file,
- * including the extensions
+ * including the extensions and skins.
*
* @return string
*/
public function getText() {
$localSettings = $this->getDefaultText();
+ if ( count( $this->skins ) ) {
+ $localSettings .= "
+# Enabled skins.
+# The following skins were automatically enabled:\n";
+
+ foreach ( $this->skins as $skinName ) {
+ $encSkinName = self::escapePhpString( $skinName );
+ $localSettings .= "require_once \"\$IP/skins/$encSkinName/$encSkinName.php\";\n";
+ }
+
+ $localSettings .= "\n";
+ }
+
if ( count( $this->extensions ) ) {
$localSettings .= "
# Enabled Extensions. Most extensions are enabled by including the base extension file here
$encExtName = self::escapePhpString( $extName );
$localSettings .= "require_once \"\$IP/extensions/$encExtName/$encExtName.php\";\n";
}
+
+ $localSettings .= "\n";
}
- $localSettings .= "\n\n# End of automatically generated settings.
+ $localSettings .= "
+# End of automatically generated settings.
# Add more configuration options below.\n\n";
return $localSettings;
wfBoolToStr( $perm ) . ";\n";
}
}
+ $groupRights .= "\n";
+
if ( ( isset( $this->groupPermissions['*']['edit'] ) &&
$this->groupPermissions['*']['edit'] === false )
&& ( isset( $this->groupPermissions['*']['createaccount'] ) &&
&& ( isset( $this->groupPermissions['*']['read'] ) &&
$this->groupPermissions['*']['read'] !== false )
) {
- $noFollow = "\n# Set \$wgNoFollowLinks to true if you open up your wiki to editing by\n"
+ $noFollow = "# Set \$wgNoFollowLinks to true if you open up your wiki to editing by\n"
. "# the general public and wish to apply nofollow to external links as a\n"
. "# deterrent to spammers. Nofollow is not a comprehensive anti-spam solution\n"
. "# and open wikis will generally require other anti-spam measures; for more\n"
. "# information, see https://www.mediawiki.org/wiki/Manual:Combating_spam\n"
- . "\$wgNoFollowLinks = false;";
+ . "\$wgNoFollowLinks = false;\n\n";
}
}
# web installer while LocalSettings.php is in place
\$wgUpgradeKey = \"{$this->values['wgUpgradeKey']}\";
-## Default skin: you can change the default skin. Use the internal symbolic
-## names, ie 'vector', 'monobook':
-\$wgDefaultSkin = \"{$this->values['wgDefaultSkin']}\";
-
## For attaching licensing metadata to pages, and displaying an
## appropriate copyright notice / icon. GNU Free Documentation
## License and Creative Commons licenses are supported so far.
# Path to the GNU diff3 utility. Used for conflict resolution.
\$wgDiff3 = \"{$this->values['wgDiff3']}\";
-{$groupRights}{$noFollow}";
+{$groupRights}{$noFollow}## Default skin: you can change the default skin. Use the internal symbolic
+## names, ie 'vector', 'monobook':
+\$wgDefaultSkin = \"{$this->values['wgDefaultSkin']}\";
+";
}
}
* var: The variable to be configured (required)
* label: The message name for the label (required)
* itemLabelPrefix: The message name prefix for the item labels (required)
+ * itemLabels: List of message names to use for the item labels instead of itemLabelPrefix, keyed by values
* values: List of allowed values (required)
* itemAttribs: Array of attribute arrays, outer key is the value name (optional)
* commonAttribs: Attribute array applied to all items
* @return string
*/
public function getRadioSet( $params ) {
- if ( !isset( $params['controlName'] ) ) {
- $params['controlName'] = 'config_' . $params['var'];
- }
-
- if ( !isset( $params['value'] ) ) {
- $params['value'] = $this->getVar( $params['var'] );
- }
+ $items = $this->getRadioElements( $params );
if ( !isset( $params['label'] ) ) {
$label = '';
} else {
$label = $params['label'];
}
+
+ if ( !isset( $params['controlName'] ) ) {
+ $params['controlName'] = 'config_' . $params['var'];
+ }
+
if ( !isset( $params['help'] ) ) {
$params['help'] = "";
}
+
$s = "<ul>\n";
+ foreach ( $items as $value => $item ) {
+ $s .= "<li>$item</li>\n";
+ }
+ $s .= "</ul>\n";
+
+ return $this->label( $label, $params['controlName'], $s, $params['help'] );
+ }
+
+ /**
+ * Get a set of labelled radio buttons. You probably want to use getRadioSet(), not this.
+ *
+ * @see getRadioSet
+ *
+ * @return array
+ */
+ public function getRadioElements( $params ) {
+ if ( !isset( $params['controlName'] ) ) {
+ $params['controlName'] = 'config_' . $params['var'];
+ }
+
+ if ( !isset( $params['value'] ) ) {
+ $params['value'] = $this->getVar( $params['var'] );
+ }
+
+ $items = array();
+
foreach ( $params['values'] as $value ) {
$itemAttribs = array();
$itemAttribs['id'] = $id;
$itemAttribs['tabindex'] = $this->nextTabIndex();
- $s .=
- '<li>' .
+ $items[$value] =
Xml::radio( $params['controlName'], $value, $checked, $itemAttribs ) .
' ' .
Xml::tags( 'label', array( 'for' => $id ), $this->parse(
- wfMessage( $params['itemLabelPrefix'] . strtolower( $value ) )->plain()
- ) ) .
- "</li>\n";
+ isset( $params['itemLabels'] ) ?
+ wfMessage( $params['itemLabels'][$value] )->plain() :
+ wfMessage( $params['itemLabelPrefix'] . strtolower( $value ) )->plain()
+ ) );
}
- $s .= "</ul>\n";
-
- return $this->label( $label, $params['controlName'], $s, $params['help'] );
+ return $items;
}
/**
/**
* @param string $var
+ * @param mixed $default
*
* @return mixed
*/
- public function getVar( $var ) {
- return $this->parent->getVar( $var );
+ public function getVar( $var, $default = null ) {
+ return $this->parent->getVar( $var, $default );
}
/**
*/
public function execute() {
if ( $this->getVar( '_SkipOptional' ) == 'skip' ) {
+ $this->submitSkins();
return 'skip';
}
if ( $this->parent->request->wasPosted() ) {
$this->getFieldSetEnd()
);
+ $skins = $this->parent->findExtensions( 'skins' );
+ $skinHtml = $this->getFieldSetStart( 'config-skins' );
+
+ if ( $skins ) {
+ $skinNames = array_map( 'strtolower', $skins );
+
+ $radioButtons = $this->parent->getRadioElements( array(
+ 'var' => 'wgDefaultSkin',
+ 'itemLabels' => array_fill_keys( $skinNames, 'config-skins-use-as-default' ),
+ 'values' => $skinNames,
+ 'value' => $this->getVar( 'wgDefaultSkin', $this->getDefaultSkin( $skinNames ) ),
+ ) );
+
+ foreach ( $skins as $skin ) {
+ $skinHtml .=
+ '<div class="config-skins-item">' .
+ $this->parent->getCheckBox( array(
+ 'var' => "skin-$skin",
+ 'rawtext' => $skin,
+ 'value' => $this->getVar( "skin-$skin", true ), // all found skins enabled by default
+ ) ) .
+ '<div class="config-skins-use-as-default">' . $radioButtons[ strtolower( $skin ) ] . '</div>' .
+ '</div>';
+ }
+ } else {
+ $skinHtml .= $this->parent->getWarningBox( wfMessage( 'config-skins-missing' )->plain() );
+ }
+
+ $skinHtml .= $this->parent->getHelpBox( 'config-skins-help' ) .
+ $this->getFieldSetEnd();
+ $this->addHTML( $skinHtml );
+
$extensions = $this->parent->findExtensions();
if ( $extensions ) {
$this->addHTML( $this->getCCDoneBox() );
}
+ /**
+ * Returns a default value to be used for $wgDefaultSkin: the preferred skin, if available among
+ * the installed skins, or any other one otherwise.
+ *
+ * @param string[] $skinNames Names of installed skins.
+ * @return string
+ */
+ public function getDefaultSkin( array $skinNames ) {
+ $defaultSkin = $GLOBALS['wgDefaultSkin'];
+ if ( in_array( $defaultSkin, $skinNames ) ) {
+ return $defaultSkin;
+ } else {
+ return $skinNames[0];
+ }
+ }
+
+ /**
+ * If the user skips this installer page, we still need to set up the default skins, but ignore
+ * everything else.
+ *
+ * @return bool
+ */
+ public function submitSkins() {
+ $skins = $this->parent->findExtensions( 'skins' );
+ $this->parent->setVar( '_Skins', $skins );
+
+ if ( $skins ) {
+ $skinNames = array_map( 'strtolower', $skins );
+ $this->parent->setVar( 'wgDefaultSkin', $this->getDefaultSkin( $skinNames ) );
+ }
+
+ return true;
+ }
+
/**
* @return bool
*/
'wgEnableEmail', 'wgPasswordSender', 'wgEnableUploads', 'wgLogo',
'wgEnableUserEmail', 'wgEnotifUserTalk', 'wgEnotifWatchlist',
'wgEmailAuthentication', 'wgMainCacheType', '_MemCachedServers',
- 'wgUseInstantCommons' ) );
+ 'wgUseInstantCommons', 'wgDefaultSkin' ) );
$retVal = true;
$this->setVar( 'wgRightsIcon', '' );
}
+ $skinsAvailable = $this->parent->findExtensions( 'skins' );
+ $skinsToInstall = array();
+ foreach ( $skinsAvailable as $skin ) {
+ $this->parent->setVarsFromRequest( array( "skin-$skin" ) );
+ if ( $this->getVar( "skin-$skin" ) ) {
+ $skinsToInstall[] = $skin;
+ }
+ }
+ $this->parent->setVar( '_Skins', $skinsToInstall );
+
+ if ( !$skinsToInstall && $skinsAvailable ) {
+ $this->parent->showError( 'config-skins-must-enable-some' );
+ $retVal = false;
+ }
+ $defaultSkin = $this->getVar( 'wgDefaultSkin' );
+ $skinsToInstallLowercase = array_map( 'strtolower', $skinsToInstall );
+ if ( $skinsToInstall && array_search( $defaultSkin, $skinsToInstallLowercase ) === false ) {
+ $this->parent->showError( 'config-skins-must-enable-default' );
+ $retVal = false;
+ }
+
$extsAvailable = $this->parent->findExtensions();
$extsToInstall = array();
foreach ( $extsAvailable as $ext ) {
"config-memcache-badport": "Memcached port numbers should be between $1 and $2.",
"config-extensions": "Extensions",
"config-extensions-help": "The extensions listed above were detected in your <code>./extensions</code> directory.\n\nThey may require additional configuration, but you can enable them now.",
+ "config-skins": "Skins",
+ "config-skins-help": "The skins listed above were detected in your <code>./skins</code> directory. You must enable at least one, and choose the default.",
+ "config-skins-use-as-default": "Use this skin as default",
+ "config-skins-missing": "No skins were found; MediaWiki will use a fallback skin until you install some proper ones.",
+ "config-skins-must-enable-some": "You must choose at least one skin to enable.",
+ "config-skins-must-enable-default": "The skin chosen as default must be enabled.",
"config-install-alreadydone": "<strong>Warning:</strong> You seem to have already installed MediaWiki and are trying to install it again.\nPlease proceed to the next page.",
"config-install-begin": "By pressing \"{{int:config-continue}}\", you will begin the installation of MediaWiki.\nIf you still want to make changes, press \"{{int:config-back}}\".",
"config-install-step-done": "done",
"config-memcache-badport": "Used as error message. Parameters:\n* $1 - 1 (hard-coded)\n* $2 - 65535 (hard-coded)\nSee also:\n* {{msg-mw|Config-memcache-badip}}\n* {{msg-mw|Config-memcache-noport}}",
"config-extensions": "{{Identical|Extension}}",
"config-extensions-help": "{{doc-important|Do not translate <code>./extensions</code>.}}\nUsed in help box.",
+ "config-skins": "{{Identical|Skin}}",
+ "config-skins-help": "{{doc-important|Do not translate <code>./skins</code>.}}\nUsed in help box.",
+ "config-skins-use-as-default": "Label shown next to skin names.",
+ "config-skins-missing": "Warning message shown when there are no skins to install.",
+ "config-skins-must-enable-some": "Error message shown when the user does silly things.",
+ "config-skins-must-enable-default": "Error message shown when the user does silly things.",
"config-install-alreadydone": "Error message shown to users visiting the installer when the wiki appears to already be set up.",
"config-install-begin": "Prompt at the end of the initial configuration options screen before the wiki software is installed.",
"config-install-step-done": "{{Identical|Done}}",
margin-left: 10em;
}
+.config-skins-item {
+ /* Clearfix */
+ clear: left;
+ overflow: hidden;
+}
+
+.config-skins-item .config-input-check {
+ margin-left: 10em;
+ width: 20em;
+ float: left;
+}
+
+.config-skins-item .config-skins-use-as-default {
+ float: left;
+}
+
.error {
color: red;
background-color: #fff;